/* Copyright(C): Leaf Johnson 2009,2010

    This file is part of leaf-lib.

    leaf-lib is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    leaf-lib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with leaf-lib.  If not, see <http://www.gnu.org/licenses/>.


 * 
 * 
 */


#ifndef UART_H_INCLUDED
#define UART_H_INCLUDED
#include <leaf/base.h>
#include <leaf/osiface.h>

#if defined(UDR3)
#define NR_UART 4
#elif defined(UDR2)
#define NR_UART 3
#elif defined(UDR1)
#define NR_UART 2
#elif defined(UDR0)
#define NR_UART 1
#endif

#define UART_R 0
#define UART_W 1
#define UART_RBRK 7
typedef enum{
	UModeR = _BV(UART_R),
	UModeW = _BV(UART_W),
	UModeRW = _BV(UART_R) | _BV(UART_W),
}UartMode;

#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <lib_bupt/usart.h>"
# define F_CPU 14745600UL
#endif
/*根据所需波特率计算UBRR, baud要为long型，一般用于串口初始化时*/
#define UBRR_FROM_BAUD(baud) (F_CPU/(16*(baud))-1)

typedef enum{
	ub600 = UBRR_FROM_BAUD( 600L ),
	ub1200 = UBRR_FROM_BAUD( 1200L ),
	ub2400 = UBRR_FROM_BAUD( 2400L ),
	ub4800 = UBRR_FROM_BAUD( 4800L ),
	ub9600 = UBRR_FROM_BAUD( 9600L ),
	ub19200 = UBRR_FROM_BAUD( 19200L ),
	ub38400 = UBRR_FROM_BAUD( 38400L ),
	ub76800 = UBRR_FROM_BAUD( 76800L ),
	ub115200 = UBRR_FROM_BAUD( 115200L ),
	ub230400 = UBRR_FROM_BAUD( 230400L ),
	ub460800 = UBRR_FROM_BAUD( 460800L ),
}UsartBaud, Ubrr;
enum CheckBitType
{
	CheckBitNone = 0,//无
	CheckBitEven = 2,//偶
	CheckBitOdd = 3,//奇
};
#define DEF_UART_BUF( name, sz ) \
	uint8_t name[ sz + 4 ]; \
	static const uint8_t name##Sz = sz

void uart_init( uint8_t no, UsartBaud ubrr, void *bufmem, uint8_t bufsz );
int uart_open( uint8_t no, UartMode mode );
int uart_close( uint8_t no, UartMode mode );
int uart_set_baud( uint8_t no, UsartBaud ubrr );
int uart_set_checkbit( uint8_t no, enum CheckBitType );
int uart_set_stopbits( uint8_t no, uint8_t stb );

int uart_write( uint8_t no, const void *buf, size_t cnt );
void uart_txi_handler( uint8_t no );

/* this function not implemented */
void uart_set_timeout( uint8_t no, unsigned int timeout );

int uart_read( uint8_t no, void *buf, size_t cnt );
void uart_read_break( uint8_t no );
void uart_rxi_handler( uint8_t no );

#define UART_TXISR( no ) \
DEF_OSISR( USART##no##_TX_vect ){ \
	enter_kernel();\
	uart_txi_handler( no );\
	enter_task();\
}

#define UART_RXISR( no ) \
DEF_OSISR( USART##no##_RX_vect ){ \
	enter_kernel();\
	uart_rxi_handler( no );\
	enter_task();\
}

#define UART_ISR( no ) \
	UART_TXISR( no ) \
	UART_RXISR( no )

#endif
